//
//  AppController.m
//  CoversEverywhere
//
//  Created by Pablo Roulet on 17/05/09.
//  Copyright 2009 Pablo Roulet. All rights reserved.
//

#import "AppController.h"
#import "FolderScanner.h"

@implementation AppController

enum { WRITING, NOT_WRITING };

NSConditionLock *conditionStatus;

- (id)init
{
	[super init];
	[[NSApplication sharedApplication] setDelegate:self];
	[mainWindow setDelegate:self];

	threadRunning = NO;
	exitThread = NO;
	
	conditionStatus = [[NSConditionLock alloc] initWithCondition:NOT_WRITING];
	
	return self;
}

- (BOOL)windowShouldClose:(id)window
{
	[self tryQuitApplication:self];
	return NO;
}

- (IBAction)tryQuitApplication:(id)sender
{
	if (threadRunning){
		NSAlert *alertFinalizando = [NSAlert alertWithMessageText:NSLocalizedString(@"ABORT_PROCESS", @"Abort process")
													defaultButton:NSLocalizedString(@"CANCEL", @"Cancel")
												  alternateButton:NSLocalizedString(@"QUIT", @"Quit")
													  otherButton:nil 	
										informativeTextWithFormat:NSLocalizedString(@"SURE_QUIT", 
																					@"Are you sure you want to quit the application?")];

		[alertFinalizando beginSheetModalForWindow:mainWindow 
									 modalDelegate:self 
									didEndSelector:@selector(alertEnded:code:context:) 
									   contextInfo:NULL];
	}else{
		[self quitApplication];
	}
}

- (void)quitApplication
{
	//Antes de salir trato de parar cualquier tarea en curso
	[self stopUpdates:nil];
	
	//Espero a que se halla terminado de escribir todos los datos antes de salir de la aplicación
	[conditionStatus lockWhenCondition:NOT_WRITING];
	
	[NSApp terminate:self];	
}

- (void)alertEnded:(NSAlert *)alert
			  code:(int)choice
		   context:(void *)v
{
	if (choice == NSAlertAlternateReturn){
		[self quitApplication];
	}
}

- (void)awakeFromNib
{
	[mainWindow setDelegate:self];
	
	[self deactivateProgBar];
	[btCancel setEnabled:NO];
	[btOpen setEnabled:YES];
	[itemOpen setEnabled:YES];
}

- (IBAction)showOpenPanel:(id)sender
{
	NSOpenPanel *openPanel = [NSOpenPanel openPanel];
	[openPanel setCanChooseDirectories:YES];
	[openPanel setAllowsMultipleSelection:YES];

	[openPanel beginSheetForDirectory:[NSHomeDirectory() stringByAppendingPathComponent:@"Music"]
								 file:nil 
								types:[NSArray arrayWithObjects:@"mp3",nil]
					   modalForWindow:mainWindow
						modalDelegate:self
					   didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) 
						  contextInfo:NULL];
}

- (void)openPanelDidEnd:(NSOpenPanel *)openPanel
			 returnCode:(int)returnCode
			contextInfo:(void *)x
{
	if (returnCode == NSOKButton){
		NSArray *files = [openPanel filenames];
		[openPanel close];
		
		//Tiene que ser un thread diferente para que no se cuelgue la UI
		[NSThread detachNewThreadSelector:@selector(startThread:) 
											 toTarget:self 
										   withObject:files];
	}
}

- (void)startThread:(NSArray *)files
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	//Adquiero el Lock para evitar que el programa pueda finalizar en medio de una operación
	[conditionStatus lock];
	
	//Voy a mandar un mensaje cuando termine el thread para actualizar la UI
	[[NSNotificationCenter defaultCenter]addObserver:self 
											selector:@selector(threadDidEnd:) 
												name:NSThreadWillExitNotification  	
											  object:[NSThread currentThread]];
	
	//Apenas entró al thread me aseguro que las variables de control este en iniciadas
	exitThread = NO;
	threadRunning = YES;
	
	//Actualizo el estado de la interfaz para mostrara posibles acciones
	[btCancel setEnabled:YES];
	[btOpen setEnabled:NO];
	[itemOpen setEnabled:NO];
	
	//Busco todos los archivos mp3
	files = [self searchFiles:files];
	
	//Modifico los archivos mp3 que fueron encontrados
	[self editFiles:files];
	
	//Libero el lock cuando ya terminé de grabar
	[conditionStatus unlockWithCondition:NOT_WRITING];
	
	threadRunning = NO;
	
	[pool release];
}

- (NSArray *)searchFiles:(NSArray *)files
{
	//Despligo un Sheet mientras se buscan los archivos MP3 en los directorios
	[NSApp beginSheet:searchSheet 
	   modalForWindow:mainWindow 
		modalDelegate:nil 
	   didEndSelector:NULL 
		  contextInfo:NULL];
	
	[prSearching startAnimation:self];
	
	FolderScanner *scanner = [[FolderScanner alloc] init];
	files = [[scanner searchForFilesIn:files withExtension:@"mp3"] retain];
	[scanner release];
	
	[prSearching stopAnimation:self];
	
	[NSApp endSheet:searchSheet];
	[searchSheet orderOut:self];
	
	return files;
}

- (void)editFiles:(NSArray *)files
{	
	//Seteo el máximo para la barra de progreso
	[self setProgBarTotal:[files count]];
	
	for (int i=0; i<[files count] && !exitThread; i++){
		
		TagAPI *fileOpened = [[TagAPI alloc] initWithGenreList:NULL];
		
		[fileOpened examineFile:[files objectAtIndex:i]];
		
		//Si tiene un Tag v2
		if ([fileOpened v2TagPresent]){			
			NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
			
			NSMutableArray *imagenes = [[fileOpened getImage] mutableCopy];

			//Verifico que el MP3 tenga alguna imagen
			if ([imagenes count] > 0){
				NSMutableDictionary *dict;
				
				//Toma la primer imagen, no me importan las otras, esto lo hago para procesar mas rapido todos los archivos
				dict = [imagenes objectAtIndex:0];
				
				//Si la imagen no es del tipo Cover (front), la modifico
				if (![[dict objectForKey:@"Picture Type"] isEqualToString:@"Cover (front)"]){
					
					[dict setObject:@"Cover (front)" forKey:@"Picture Type"];
				
					//Guardo los cambios
					[fileOpened setImages:imagenes];
					[fileOpened updateFile];
				}
			}
			[imagenes release];
			imagenes = nil;
			
			[pool release];
		}

		[self increaseProgBarValue];
		
		[fileOpened release];
		fileOpened = nil;		
	}
}

- (void)setProgBarTotal:(int)total
{
	[tfProgreso setHidden:NO];
	
	//Reinicio el contador a 0
	[self willChangeValueForKey:@"progBarValue"];
	progBarValue = 0;
	[self didChangeValueForKey:@"progBarValue"];	
	
	//Seteo el máximo de archivos a modificar
	[self willChangeValueForKey:@"progBarTotal"];
	progBarTotal = total;
	[self didChangeValueForKey:@"progBarTotal"];	
	
	[self updateProgLabel];
}

- (void)increaseProgBarValue
{
	[self willChangeValueForKey:@"progBarValue"];
	progBarValue++;
	[self didChangeValueForKey:@"progBarValue"];

	[self updateProgLabel];
}

- (void)updateProgLabel
{
	[tfProgreso setStringValue:[NSString stringWithFormat:NSLocalizedString(@"FILES_COMPLETED", @"%i of %i completed"), progBarValue, progBarTotal]];	
}

- (void)deactivateProgBar
{
	//Reseteo la barra de progreso y oculto el label con la cantidad de archivos modificados
	[self setProgBarTotal:100];
	[tfProgreso setHidden:YES];
}

- (IBAction)stopUpdates:(id)sender
{	
	exitThread = YES;
}

- (void)threadDidEnd:(NSNotification *)aNotification
{	
	NSString *alertTitle;
	NSString *alertText;
	
	//Me fijo si se terminaron todas las operaciones o hubo una interrupción
	if (progBarValue != progBarTotal){
		alertTitle = [NSString stringWithFormat:NSLocalizedString(@"OPERATION_INTERRUPTED", 
																  @"Operation interrupted")];
		if (progBarValue > 1) 
			alertText = [NSString stringWithFormat:NSLocalizedString(@"OI_FILES_MOD_PLURAL",
																	 @"\nOnly %i files of %i were modified"), progBarValue, progBarTotal];
		else
			alertText = [NSString stringWithFormat:NSLocalizedString(@"OI_FILES_MOD_SINGULAR",
																	 @"\nOnly %i file of %i was modified"), progBarValue, progBarTotal];
	}else{
		alertTitle = [NSString stringWithFormat:NSLocalizedString(@"OPERATION_COMPLETED", 
																  @"Operation completed")];
		if (progBarValue > 1) 
			alertText = [NSString stringWithFormat:NSLocalizedString(@"OC_FILES_MOD_PLURAL",
																	 @"\n%i files were modified"), progBarValue];
		else
			alertText = [NSString stringWithFormat:NSLocalizedString(@"OC_FILES_MOD_SINGULAR",
																	 @"\n%i file was modified"), progBarValue];
	}

	
	NSAlert *alertResumen = [NSAlert alertWithMessageText:alertTitle 
												defaultButton:NSLocalizedString(@"OK", @"OK")
											  alternateButton:nil 
												  otherButton:nil 	
									informativeTextWithFormat:alertText];
	
	[alertResumen runModal];
	
	[self deactivateProgBar];
	[btCancel setEnabled:NO];
	[btOpen setEnabled:YES];
	[itemOpen setEnabled:YES];
}

- (void)dealloc
{
	[conditionStatus release];
	[super dealloc];
}	

@end
